#include "GameplayState.h"
#include "TileSystem.h"
#include "../SGD Wrappers/SGD_InputManager.h"
#include "..\\SGD Wrappers\\SGD_Geometry.h"
#include "Game.h"
#include "GameObject.h"
#include "MainMenuState.h"
#include "stdafx.h"
#include "ParticleSystem.h"
#include "Emitter.h"
#include "Augment.h"
#include <sstream>
#include <iomanip>
#include "ArcaneShot.h"
#include "Portal.h"
#include "Ladder.h"
#include "Stairs.h"
#include "CreatePortalMessage.h"
#include "CreateLadderMessage.h"
#include "CreateStairsMessage.h"
#include "CreateOgreMessage.h"
#include "CreateBulletMessage.h"
#include "VictoryState.h"
#include "../TinyXML/tinyxml.h"
#include <Windows.h>
#include <shlobj.h>

#include "DoubleJump.h"

#define FORCHECKOFF 0
#define GAMEOVERLASTOPTION 2

/**************************************************************/
// GetInstance
//	- store the ONLY instance in global memory
//	- return the only instance by pointer
/*static*/ GameplayState* GameplayState::GetInstance(void)
{
	static GameplayState s_Instance;

	return &s_Instance;
}

/**************************************************************/
// Enter
//	- reset the game & load resources
/*virtual*/ void GameplayState::Enter(void)
{
	//Set the theGame pointer to the game instance
	theGame = Game::GetInstance();

	m_hOptionsBar = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/volumeBars.png");

	// Allocate the Object Manager
	if (m_pObjects != nullptr)
	{
		m_pObjects->RemoveAll();
		delete m_pObjects;
		m_pObjects = nullptr;
	}
	m_pObjects = new ObjectManager;

	//set the pAudio pointer to the audiomanager's instance
	pAudio = SGD::AudioManager::GetInstance();

	//Load Sounds
	if (m_AOptionsVolume == SGD::INVALID_HANDLE)
		m_AOptionsVolume = pAudio->LoadAudio("resource/Sounds/OptionsVolume.wav");
	if (m_AOptionsVolume2 == SGD::INVALID_HANDLE)
		m_AOptionsVolume2 = pAudio->LoadAudio("resource/Sounds/OptionsVolume.xwm");

	if (pAudio->IsAudioPlaying(Game::GetInstance()->GetSong(Game::GetInstance()->MENU)))
		pAudio->StopAudio(Game::GetInstance()->GetSong(Game::GetInstance()->MENU));

	pAudio->PlayAudio(theGame->GetSong(0), true);

	// Set background color
	SGD::GraphicsManager::GetInstance()->SetClearColor({ 50, 50, 50 });	// dark gray

	if (forestBackground == SGD::INVALID_HANDLE)
		forestBackground = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/forest.png");
	if (caveBackground == SGD::INVALID_HANDLE)
		caveBackground = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/cave1.png");
	if (castleBackground == SGD::INVALID_HANDLE)
		castleBackground = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/castle.png");
	if (volcanoBackground == SGD::INVALID_HANDLE)
		volcanoBackground = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/volcano2.png");
	if (bulletImage == SGD::INVALID_HANDLE)
		bulletImage = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/projectiles.png");
	if (hudImage == SGD::INVALID_HANDLE)
		hudImage = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/Hud.png");
	if (dpad == SGD::INVALID_HANDLE)
		dpad = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/dpad.png");
	if (vineImage == SGD::INVALID_HANDLE)
		vineImage = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/vine.png");
	if (shield == SGD::INVALID_HANDLE)
		shield = SGD::GraphicsManager::GetInstance()->LoadTexture("resource/Graphics/blueShield.png");
	animSys = AnimationSystem::GetInstance();

	if (!animationsLoaded)
	{
		animSys->GetAnimationInfoFromFile("HeroAnimation.xml");
		animSys->GetAnimationInfoFromFile("ElfAnimation.xml");
		animSys->GetAnimationInfoFromFile("GoblinAnimation.xml");
		animSys->GetAnimationInfoFromFile("BatAnimation.xml");
		animSys->GetAnimationInfoFromFile("VampireAnimation.xml");
		animSys->GetAnimationInfoFromFile("OgreAnimation.xml");
		animSys->GetAnimationInfoFromFile("DragonAnimation.xml");
		animSys->GetAnimationInfoFromFile("GiantSpiderAnimation.xml");
		animSys->GetAnimationInfoFromFile("KnightAnimation.xml");
		animSys->GetAnimationInfoFromFile("ArcherAnimation.xml");
		animationsLoaded = true;
	}

	// particle system link
	particleSystem = ParticleSystem::GetInstance();

	//Load all emitters from directory
	particleSystem->LoadEmitters();

	//Load Levels
	TS = TileSystem::GetInstance();
#if FORCHECKOFF
	TS->Load("./resource/Levels/", "AugmentTest.xml");
#else
	TS->Load("./resource/Levels/", "base.xml");
#endif

	LoadUCC();

	// Initialize the Event Manager
	m_pEvents = SGD::EventManager::GetInstance();
	m_pEvents->Initialize();

	// Initialize the Message Manager
	m_pMessages = SGD::MessageManager::GetInstance();
	m_pMessages->Initialize(&MessageProc);

	m_bPaused = false;

	SetLevel(0);
	m_pEvents->Update();
	m_pMessages->Update();

	//Load saved game from file
	string tempName = LoadGameState::GetInstance()->GetPlayerName();
	string loadPath = LoadGameState::GetInstance()->GetFile();
	LoadPlayerFile(loadPath);
	player->SetName(tempName.c_str());
	SavePlayerFile(loadPath.c_str());
}
/**************************************************************/
// Exit
//	- deallocate / unload resources
/*virtual*/ void GameplayState::Exit(void)
{
	SGD::AudioManager::GetInstance()->UnloadAudio(m_AOptionsVolume);
	SGD::AudioManager::GetInstance()->UnloadAudio(m_AOptionsVolume2);

	pAudio->StopAudio(theGame->GetSong(currLevel));

	SGD::GraphicsManager::GetInstance()->UnloadTexture(bulletImage);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(forestBackground);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(caveBackground);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(castleBackground);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(volcanoBackground);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(hudImage);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(dpad);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(vineImage);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(shield);

	SGD::GraphicsManager::GetInstance()->UnloadTexture(m_hOptionsBar);

	//if (basePortal != nullptr)
	//	basePortal->Release();

	//animSys->UnloadTexture();
	//animSys->DeleteInstance();

	TS->Unload();
	levelOne = 0;
	levelTwo = 0;
	levelThree = 0;
	levelFour = 0;
	TS->DeleteInstance();



	// Deallocate the Object Manager
	//player->Release();
	player = nullptr;
	m_pObjects->RemoveAll();
	delete m_pObjects;
	m_pObjects = nullptr;
	

	// Terminate & deallocate the SGD wrappers
	m_pEvents->Terminate();
	m_pEvents = nullptr;
	SGD::EventManager::DeleteInstance();

	m_pMessages->Terminate();
	m_pMessages = nullptr;
	SGD::MessageManager::DeleteInstance();

	particleSystem->Exit();
	particleSystem->DeleteInstance();
}

/**************************************************************/
// Input
//	- Handles Input 
/*virtual*/ bool GameplayState::Input(void)
{
	SGD::InputManager* input = SGD::InputManager::GetInstance();
	if (Game::GetInstance()->PauseInput())
	{
		m_bPaused = !m_bPaused;
		if (m_bPaused)
		{
			displayUCC = false;
			m_nCursor = 0;
		}
	}

	/*DEBUG tools*/
	
	if (m_bPaused && htpMenuIsOpen)
	{
		if (theGame->MenuConfirmInput())
		{
			m_nCursor++;
			if (m_nCursor > 2)
				htpMenuIsOpen = false;
		}
		else if (theGame->MenuBackInput())
		{
			m_nCursor--;
			if (m_nCursor < 0)
				htpMenuIsOpen = false;
		}
	}
	else if (m_bPaused == true)
	{
		SGD::InputManager* pInput = SGD::InputManager::GetInstance();

		if (Game::GetInstance()->MenuConfirmInput())
		{
			if (m_nCursor == 2)
			{
				pAudio->PlayAudio(theGame->GetMenuConfirm());
				SGD::GraphicsManager::GetInstance()->Resize({ (float)Game::GetInstance()->GetScreenWidth(), (float)Game::GetInstance()->GetScreenHeight() }, Game::GetInstance()->GetWindowd());
				theGame->SetWindowd(!Game::GetInstance()->GetWindowd());
			}
			else if (m_nCursor == 3)
			{
				htpMenuIsOpen = true;
				m_nCursor = 0;
			}
			else if (m_nCursor == 4)
			{
				pAudio->PlayAudio(theGame->GetMenuConfirm());
				theGame->ChangeState(MainMenuState::GetInstance());
			}
		}

		// Move cursor
		if (Game::GetInstance()->MenuDownInput())
		{
			++m_nCursor;

			// Wrap around
			if (m_nCursor > 4)
				m_nCursor = 0;
		}
		else if (Game::GetInstance()->MenuUpInput())
		{
			--m_nCursor;

			// Wrap around
			if (m_nCursor < 0)
				m_nCursor = 4;
		}

		if (Game::GetInstance()->MenuLeftInput())
		{
			if (m_nCursor == 0)
			{
				if (Game::GetInstance()->GetMusicVol() > 0)
				{
					int music = Game::GetInstance()->GetMusicVol();
					Game::GetInstance()->SetMusicVol(music - 5);
					SGD::AudioManager::GetInstance()->SetMasterVolume(SGD::AudioGroup::Music, Game::GetInstance()->GetMusicVol());

				}
			}
			if (m_nCursor == 1)
			{
				if (Game::GetInstance()->GetSoundVol() > 0)
				{
					int sounds = Game::GetInstance()->GetSoundVol();
					Game::GetInstance()->SetSoundVol(sounds - 5);
					SGD::AudioManager::GetInstance()->SetMasterVolume(SGD::AudioGroup::SoundEffects, Game::GetInstance()->GetSoundVol());
					SGD::AudioManager::GetInstance()->PlayAudio(m_AOptionsVolume);

				}
			}
		}
		if (Game::GetInstance()->MenuRightInput())
		{
			if (m_nCursor == 0)
			{
				if (Game::GetInstance()->GetMusicVol() < 100)
					Game::GetInstance()->SetMusicVol(Game::GetInstance()->GetMusicVol() + 5);
				SGD::AudioManager::GetInstance()->SetMasterVolume(SGD::AudioGroup::Music, Game::GetInstance()->GetMusicVol());

			}
			if (m_nCursor == 1)
			{
				if (Game::GetInstance()->GetSoundVol() < 100)
					Game::GetInstance()->SetSoundVol(Game::GetInstance()->GetSoundVol() + 5);
				SGD::AudioManager::GetInstance()->SetMasterVolume(SGD::AudioGroup::SoundEffects, Game::GetInstance()->GetSoundVol());
				SGD::AudioManager::GetInstance()->PlayAudio(m_AOptionsVolume);

			}
		}
	}
	else if (displayUCC)
	{
		SGD::InputManager* pInput = SGD::InputManager::GetInstance();

		// Move cursor
		if (theGame->MenuDownInput())
		{
			++m_nCursor;

			// Wrap around
			if (m_nCursor > int(uccList.size()))
				m_nCursor = 0;
		}
		else if (theGame->MenuUpInput())
		{
			--m_nCursor;

			// Wrap around
			if (m_nCursor < 0)
				m_nCursor = uccList.size();
		}
		else if ((theGame->MenuConfirmInput()) && uccList.size() > 0)
		{
			char my_documents[MAX_PATH];
			HRESULT result = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
			strcat_s(my_documents, "\\MegaLands\\");
			string file = uccList[m_nCursor] + ".xml";
			SetLevel(TS->Load(my_documents, file.c_str()) + 4);
			displayUCC = false;
		}
		else if (theGame->LeftInput(pInput->GetLeftJoystick(0)) || theGame->RightInput(pInput->GetLeftJoystick(0)))
			player->Input();

	}
	else
	{
		player->Input();
		if (displayUCC)
			m_nCursor = 0;
	}
	if (player != nullptr && !player->GetIsAlive())
	{
		//game over menu cycling
		if (theGame->MenuUpInput())
			gameoverCursor--;
		else if (theGame->MenuDownInput())
			gameoverCursor++;

		//gameover menu wrap around
		if (gameoverCursor > GAMEOVERLASTOPTION)
			gameoverCursor = 0;
		else if (gameoverCursor < 0)
			gameoverCursor = GAMEOVERLASTOPTION;
	}
	return true;
}

/**************************************************************/
// Update
//	- update Objects / animations
/*virtual*/ void GameplayState::Update(float elapsedTime)
{
	if (player->GetNextLevel() == finalLevel + 1 && !gameComplete)
	{
		gameComplete = true;

		//need to save the data here
		SavePlayerFile(LoadGameState::GetInstance()->GetFile());

		Game::GetInstance()->ChangeState(VictoryState::GetInstance());
		return;
	}

	if (!m_bPaused && player->GetIsAlive())
	{
		TS->SpawnEnemies(mapIndex);
		m_pObjects->UpdateAll(elapsedTime);

		if (player)
			player->SetClosestEnemy(m_pObjects->ReturnClosestEnemy());
		m_pObjects->CheckCollisions(ObjBuckets::PLAYER_BUCKET, ObjBuckets::ENEMY_BUCKET);
		m_pObjects->CheckCollisions(ObjBuckets::PLAYER_BUCKET, ObjBuckets::ENEMY_BULLET_BUCKET);

		m_pObjects->CheckCollisions(ObjBuckets::ENEMY_BUCKET, ObjBuckets::PLAYER_BUCKET);
		m_pObjects->CheckCollisions(ObjBuckets::ENEMY_BUCKET, ObjBuckets::PLAYER_BULLET_BUCKET);

		m_pObjects->CheckCollisions(ObjBuckets::ENEMY_BUCKET, ObjBuckets::ENEMY_BUCKET);

		// Process the events & messages
		//m_pObjects->UpdateAll(elapsedTime);
		m_pObjects->CheckCollisions(ObjBuckets::PLAYER_BUCKET, ObjBuckets::PORTAL_BUCKET);
		m_pObjects->CheckCollisions(ObjBuckets::PLAYER_BUCKET, ObjBuckets::OBJ_BUCKET);
		m_pObjects->CheckCollisions(ObjBuckets::PLAYER_BUCKET, ObjBuckets::AUGMENT_BUCKET);
		m_pObjects->CheckCollisions(ObjBuckets::PLAYER_BUCKET, ObjBuckets::PLAYER_BULLET_BUCKET);

		if (!player->GetUCCPortal())
			displayUCC = false;
		TS->CheckCollison(mapIndex, m_pObjects->ReturnObject(ObjBuckets::PLAYER_BUCKET, 0));
		GameObject *obj;
		for (int i = 0; obj = m_pObjects->ReturnObject(ObjBuckets::OBJ_BUCKET, i); i++)
		{
			TS->CheckCollison(mapIndex, obj);
		}
		for (int i = 0; obj = m_pObjects->ReturnObject(ObjBuckets::PORTAL_BUCKET, i); i++)
		{
			TS->CheckCollison(mapIndex, obj);
		}
		for (int i = 0; obj = m_pObjects->ReturnObject(ObjBuckets::PLAYER_BULLET_BUCKET, i); i++)
		{
			TS->CheckCollison(mapIndex, obj);
		}
		for (int i = 0; obj = m_pObjects->ReturnObject(ObjBuckets::ENEMY_BULLET_BUCKET, i); i++)
		{
			TS->CheckCollison(mapIndex, obj);
		}


		//Loop through all enemies calling check collision
		GameObject *temp;
		for (int i = 0; temp = m_pObjects->ReturnObject(ObjBuckets::ENEMY_BUCKET, i); i++)
		{
			TS->CheckCollison(mapIndex, temp);
		}
		m_pEvents->Update();
		m_pMessages->Update();
	}
	else if (!player->GetIsAlive())
	{
		player->SetScore(0);
		if (theGame->MenuConfirmInput() && gameoverCursor == 0)
		{
			gameoverCursor = 0;
			//return to hub world
			SetLevel(0);
			player->SetIsAlive(true);
		}
		else if (theGame->MenuConfirmInput() && gameoverCursor == 1)
		{
			gameoverCursor = 0;
			//restart level
			SetLevel(currLevel);
			player->SetHealth(player->GetMaxHealth());
			player->SetIsAlive(true);
		}
		else if (theGame->MenuConfirmInput() && gameoverCursor == 2)
		{
			gameoverCursor = 0;
			//return to main menu
			Game::GetInstance()->ChangeState(MainMenuState::GetInstance());
		}
	}
}

/**************************************************************/
// Render
//	- Render Objects / animations
/*virtual*/ void GameplayState::Render(void)
{
	SGD::GraphicsManager * pGraphics = SGD::GraphicsManager::GetInstance();
	if (m_bPaused && htpMenuIsOpen)
	{
		// Use the game's font
		BitmapFont* pFont = Game::GetInstance()->GetFont();

		// Align text based on window width
		int width = (int)Game::GetInstance()->GetScreenWidth();

		SGD::GraphicsManager * pGraphics = SGD::GraphicsManager::GetInstance();

		pGraphics->DrawTexture(theGame->GetMenuBackground(), { 0, 0 });

		switch (m_nCursor)
		{
		case 0:
		{
			pGraphics->DrawTextureSection(theGame->GetHTPImage(), { 0, 0 }, { 0, 0, 800, 600 });
		}
			break;
		case 1:
		{
			pGraphics->DrawTextureSection(theGame->GetControllerImage(), { 0, 100 }, { 0, 0, 675, 390 });//675x390
			pFont->Draw("CONTROLLER INPUT", (int)((width - (4 * 32 * 4.0f)) / 2) - 50, 50, 1.0f, { 255, 0, 0 });
			pFont->Draw("Press A for Keyboard", 25, 500, .6f, { 255, 0, 0 });
			pFont->Draw("Press B to Exit", 25, 535, .6f, { 255, 0, 0 });
		}
			break;
		case 2:
		{
			pGraphics->DrawTextureSection(theGame->GetControllerImage(), { 0, 0 }, { 0, 410, 710, 970 });//710x540
			//	 pFont->Draw("KEYBOARD INPUT", (int)((width - (4 * 32 * 4.0f)) / 2) - 50, 50, 1.0f, { 255, 0, 0 });
			pFont->Draw("Press A for Instructions", 425, 500, .6f, { 255, 0, 0 });
			pFont->Draw("Press B to Exit", 425, 535, .6f, { 255, 0, 0 });
		}
			break;
		default:
			break;
		}
	}
	else if (m_bPaused)
	{
		// Use the game's font
		BitmapFont* pFont = Game::GetInstance()->GetFont();
		// Align text based on window width
		int width = (int)Game::GetInstance()->GetScreenWidth();
		SGD::GraphicsManager * pGraphics = SGD::GraphicsManager::GetInstance();
		
		float sound = float(Game::GetInstance()->GetSoundVol());
		float music = float(Game::GetInstance()->GetMusicVol());

		pGraphics->DrawTexture(theGame->GetMenuBackground(), { 0, 0 });
		// Display the game title centered at 4x scale
		pFont->Draw("PAUSED", (int)((width - (6 * 34 * 1.0f)) / 2), 50, 1.0f, {});

		pFont->Draw("Music Volume", 300, 150, 0.7f, {});
		pGraphics->DrawTextureSection(m_hOptionsBar, { 300, 200 }, { 17, 41, 434, 63 });
		pGraphics->DrawRectangle({ 307 + (music * 4), 195, 314 + (music * 4), 228 }, { 0, 0, 0, 0 }, { 0, 0, 0 }, 3);
		//	pGraphics->DrawRectangle({ 325.0f, 150.0f, 350.0f + (music * 4.0f), 200.0f }, { 255, 0, 0 });
		pFont->Draw("Sound Volume", 300, 250, 0.7f, {});
		pGraphics->DrawTextureSection(m_hOptionsBar, { 300, 300 }, { 17, 41, 434, 63 });
		pGraphics->DrawRectangle({ 307 + (sound * 4), 295, 314 + (sound * 4), 328 }, { 0, 0, 0, 0 }, { 0, 0, 0 }, 3);
		//pGraphics->DrawRectangle({ 325.0f, 250.0f, 350.0f + (sound * 4.0f), 300.0f }, { 255, 0, 0 });
		pFont->Draw("FullScreen", 300, 350, 0.7f, {});
		pFont->Draw("How To Play", 300, 410, 0.7f, {});
		pFont->Draw("Exit(B)", 300, 470, 0.7f, {});
		
		// Display the cursor next to the option
		float offset;
		if (m_nCursor < 2)
			offset = 100.0f * m_nCursor;
		else
			offset = 30.0f + (60 * m_nCursor);
		SGD::GraphicsManager::GetInstance()->DrawTextureSection(theGame->GetCursorImage(), { 150, 200 + offset }, { 0, 0, 100, 35 });
	}
	else if (!player->GetIsAlive())
	{
		// Use the game's font
		BitmapFont* pFont = Game::GetInstance()->GetFont();

		pFont->Draw("GAME OVER", 300, 100, 1, {});
		pFont->Draw("Return to base\nRestart level\nReturn to main menu", 100, 400, 1, {});
		pGraphics->DrawTexture(theGame->GetCursorImage(), { 50.0f, 400.0f + 50 * gameoverCursor });
	}
	else
	{
		Game* game = Game::GetInstance();

		if (currLevel == game->FOREST)
			pGraphics->DrawTextureSection(forestBackground, { 0, 0 }, { 0, 0, 800, 600 });
		else if (currLevel == game->CAVE)
			pGraphics->DrawTextureSection(caveBackground, { 0, 0 }, { 0, 0, 800, 600 });
		else if (currLevel == game->CASTLE)
			pGraphics->DrawTextureSection(castleBackground, { 0, 0 }, { 0, 0, 800, 600 });
		else if (currLevel == game->VOLCANO)
			pGraphics->DrawTextureSection(volcanoBackground, { 0, 0 }, { 0, 0, 800, 600 });

		Game::GetInstance()->SetCameraPos(player->GetPosition(), SGD::Rectangle(0, 0, 0, 0));

		TS->Render(mapIndex, game->GetCameraPos(), game->GetScreenWidth(), game->GetScreenHeight());
		m_pObjects->RenderAll();
		HUD();

#pragma region playerScore debug code
#if 0
		stringstream scoreTest;
		scoreTest << "player score: " << player->GetScore();
		SGD::GraphicsManager::GetInstance()->DrawString(scoreTest.str().c_str(), { 50, 300 }, { 255, 0, 0 });
#endif
#pragma endregion

		if (displayUCC)
		{
			std::ostringstream ossUCC;

			float start = 0.0f;
			float end = 5.0f;
			int marker = m_nCursor;

			if (m_nCursor > 4)
			{
				start = m_nCursor - 4.0f;
				end = float(m_nCursor);
				marker = 4;
			}

			if (start > 0)
				ossUCC << "LESS" << endl;
			for (unsigned int i = unsigned int(start); i < uccList.size() && i < end; i++)
			{
				ossUCC << uccList[i] << endl;
			}
			if (m_nCursor < int(uccList.size()) && uccList.size() > end)
				ossUCC << "MORE";

			SGD::Rectangle menuRect;
			menuRect.left = ((Game::GetInstance()->GetScreenWidth() - (7 * 32)) / 2) - 100;
			menuRect.top = Game::GetInstance()->GetScreenHeight() / 10;
			menuRect.right = menuRect.left + 400;
			menuRect.bottom = menuRect.top + 400;

			pGraphics->DrawRectangle(menuRect, SGD::Color(196, 0, 0, 0), SGD::Color(255, 255, 0, 0));
			Game::GetInstance()->GetFont()->Draw("Load Level", int(menuRect.left) + 100, int(menuRect.top), .6f, { 255, 255, 255 });
			Game::GetInstance()->GetFont()->Draw(ossUCC.str().c_str(), int(menuRect.left) + 100, int(menuRect.top) + 100, 1.0f, { 255, 255, 255 });
			SGD::GraphicsManager::GetInstance()->DrawTextureSection(theGame->GetCursorImage(), { menuRect.left, Game::GetInstance()->GetScreenHeight() / 10 + (50 * marker) + 100 }, { 0, 0, 100, 35 });
		}
	}
}
/***********************************************************************
MessageProc
- callback function to process messages queued in the Message Manager
- STATIC METHOD
- does not have an invoking object
- must use the singleton to access data members
***********************************************************************/

void GameplayState::MessageProc(const SGD::Message* pMsg)
{
	/* Show warning when a Message ID enumerator is not handled */
#pragma warning( push )
#pragma warning( 1 : 4061 )


	// What type of message is it?
	switch (pMsg->GetMessageID())
	{
	case MessageID::MSG_CREATE_PLAYER:
	{
										 const CreatePlayerMessage* pCreatePlayer = dynamic_cast<const CreatePlayerMessage*>(pMsg);
										 GameObject * ptr = GameplayState::GetInstance()->CreatePlayer(pCreatePlayer->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::PLAYER_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_WEAPONTABLE:
	{
											  const CreateWeaponAugmentTable* pCreateTable = dynamic_cast<const CreateWeaponAugmentTable*>(pMsg);
											  GameObject * ptr = GameplayState::GetInstance()->CreateAugmentTable(pCreateTable->GetPosition(), pCreateTable->GetTableType());
											  GameplayState::GetInstance()->m_pObjects->AddObject(ptr, OBJ_BUCKET);
											  ptr->Release();
											  ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_AUGMENT:
	{
										  const CreateAugmentMessage* pCreateAugment =
											  dynamic_cast<const CreateAugmentMessage*>(pMsg);
										  GameObject * ptr = GameplayState::GetInstance()->CreateAugment(pCreateAugment->GetPosition(), pCreateAugment->GetAugName());
										  GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::AUGMENT_BUCKET);
										  ptr->Release();
										  ptr = nullptr;

	}
		break;
	case MessageID::MSG_CREATE_PICKUP_HEALTH:
	{
												const CreatePickupHealthMessage* pCreateHealth = dynamic_cast<const CreatePickupHealthMessage*>(pMsg);
												GameObject * ptr = GameplayState::GetInstance()->CreateHealthPickup(pCreateHealth->GetPosition());
												GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::OBJ_BUCKET);
												ptr->Release();
												ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_PICKUP_SHIELD:
	{
												const CreatePickupShieldMessage* pCreateShield = dynamic_cast<const CreatePickupShieldMessage*>(pMsg);
												GameObject * ptr = GameplayState::GetInstance()->CreateShieldPickup(pCreateShield->GetPosition());
												GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::OBJ_BUCKET);
												ptr->Release();
												ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_BULLET:
	{
										 const CreateBulletMessage* pCreateBullet = dynamic_cast<const CreateBulletMessage*>(pMsg);
										 GameObject * ptr = GameplayState::GetInstance()->CreateProjectile(pCreateBullet->GetOwner(), pCreateBullet->GetRotation(), pCreateBullet->GetUseFacing(), "SmokeyEffect");
										 Projectile *b_ptr = (Projectile *)ptr;
										 if (dynamic_cast<Enemy *>(b_ptr->GetOwner()))
											 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BULLET_BUCKET);
										 else
											 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::PLAYER_BULLET_BUCKET);

										 ptr->Release();
										 ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_GOBLIN:
	{
										 const CreateGoblinMessage* pCreateGoblin =
											 dynamic_cast<const CreateGoblinMessage*>(pMsg);
										 GameObject * ptr =
											 GameplayState::GetInstance()->CreateGoblin(pCreateGoblin->GetPosition());

										 dynamic_cast<Goblin *>(ptr)->SetCanSpawnFriends(pCreateGoblin->GetCanSpawnFriends());
										 dynamic_cast<Goblin *>(ptr)->angry = pCreateGoblin->IsAngry();

										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
										 //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_KNIGHT:
	{
										 const CreateKnightMessage* pCreateKnight = dynamic_cast<const CreateKnightMessage*>(pMsg);
										 GameObject * ptr = GameplayState::GetInstance()->CreateKnight(pCreateKnight->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
										 //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_ELF:
	{
									  const CreateElfMessage* pCreateElf = dynamic_cast<const CreateElfMessage*>(pMsg);
									  GameObject * ptr = GameplayState::GetInstance()->CreateElf(pCreateElf->GetPosition());
									  GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
									  ptr->Release();
									  ptr = nullptr;
									  //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_ARCHER:
	{
										 const CreateArcherMessage* pCreateArcher = dynamic_cast<const CreateArcherMessage*>(pMsg);
										 GameObject * ptr = GameplayState::GetInstance()->CreateArcher(pCreateArcher->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
										 //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_BAT:
	{
									  const CreateBatMessage* pCreateBat = dynamic_cast<const CreateBatMessage*>(pMsg);

									  GameObject* ptr;
									  if (pCreateBat->GetOwner())
										  ptr = GameplayState::GetInstance()->CreateBat(pCreateBat->GetPosition(), true);
									  else
										  ptr = GameplayState::GetInstance()->CreateBat(pCreateBat->GetPosition());

									  GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
									  dynamic_cast<Bat *>(ptr)->SetOwner(pCreateBat->GetOwner());
									  ptr->Release();
									  ptr = nullptr;
									  //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_SPIDER:
	{
										 const CreateSpiderMessage* pCreateSpider = dynamic_cast<const CreateSpiderMessage*>(pMsg);
										 GameObject * ptr = GameplayState::GetInstance()->CreateSpider(pCreateSpider->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
										 //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_OGRE:
	{
									   const CreateOgreMessage* pCreateOgre = dynamic_cast<const CreateOgreMessage*>(pMsg);
									   GameObject * ptr = GameplayState::GetInstance()->CreateOgre(pCreateOgre->GetPosition());
									   GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
									   ptr->Release();
									   ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_VAMPIRE:
	{
										  const CreateVampireMessage* pCreateVampire = dynamic_cast<const CreateVampireMessage*>(pMsg);
										  GameObject * ptr = GameplayState::GetInstance()->CreateVampire(pCreateVampire->GetPosition());
										  GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
										  ptr->Release();
										  ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_GIANT_SPIDER:
	{
											   const CreateGiantSpiderMessage* pCreateGiantSpider = dynamic_cast<const CreateGiantSpiderMessage*>(pMsg);
											   GameObject * ptr = GameplayState::GetInstance()->CreateGiantSpider(pCreateGiantSpider->GetPosition());
											   GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
											   ptr->Release();
											   ptr = nullptr;							   //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_DRAGON:
	{
										 const CreateDragonMessage* pCreateDragon = dynamic_cast<const CreateDragonMessage*>(pMsg);
										 GameObject * ptr = GameplayState::GetInstance()->CreateDragon(pCreateDragon->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::ENEMY_BUCKET);
										 ptr->Release();
										 ptr = nullptr;				 //CreateEnemy();
	}
		break;
	case MessageID::MSG_CREATE_LEVEL_PORTAL:
	{
											   const CreatePortalMessage* pCreatePortal = dynamic_cast<const CreatePortalMessage*>(pMsg);
											   GameObject* ptr = GameplayState::GetInstance()->CreatePortal(pCreatePortal->GetLevel(), pCreatePortal->GetPosition());
											   GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::PORTAL_BUCKET);
											   ptr->Release();
											   ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_UCC_PORTAL:
	{
											 const CreatePortalMessage* pCreatePortal = dynamic_cast<const CreatePortalMessage*>(pMsg);
											 GameObject* ptr = GameplayState::GetInstance()->CreatePortal(pCreatePortal->GetPosition());
											 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::PORTAL_BUCKET);
											 ptr->Release();
											 ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_WARP_PORTAL:
	{
											  const CreatePortalMessage* pCreatePortal = dynamic_cast<const CreatePortalMessage*>(pMsg);
											  GameObject* ptr = GameplayState::GetInstance()->CreatePortal(pCreatePortal->GetWarpLoc(), pCreatePortal->GetPosition());
											  GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::PORTAL_BUCKET);
											  ptr->Release();
											  ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_LADDER:
	{
										 const CreateLadderMessage* pCreateLadder = dynamic_cast<const CreateLadderMessage*>(pMsg);
										 GameObject* ptr = GameplayState::GetInstance()->CreateLadder(pCreateLadder->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::OBJ_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
	}
		break;
	case MessageID::MSG_CREATE_STAIRS:
	{
										 const CreateStairsMessage* pCreateStairs = dynamic_cast<const CreateStairsMessage*>(pMsg);
										 GameObject* ptr = GameplayState::GetInstance()->CreateStairs(pCreateStairs->GetPosition());
										 GameplayState::GetInstance()->m_pObjects->AddObject(ptr, ObjBuckets::OBJ_BUCKET);
										 ptr->Release();
										 ptr = nullptr;
	}
		break;
	case MessageID::MSG_DESTROY_OBJECT:
	{
		{
			// Downcast to the actual message type
			const DestroyGameObjectMessage* pDestroyMsg =
			dynamic_cast<const DestroyGameObjectMessage*>(pMsg);

			//	  assert(pDestroyMsg != nullptr
			//		  && "Game::MessageProc - MSG_DESTROY_ENTITY is not actually a DestroyEntityMessage");

			if (pDestroyMsg->GetEntity())
			{
				GameObject* ptr = pDestroyMsg->GetEntity();

				// Use the Game singleton to access members!
				GameplayState::GetInstance()->m_pObjects->RemoveObject(ptr);
			}
		}
										  break;
	}
		break;
	default:
		break;
	}

	/* Restore previous warning levels */
#pragma warning( pop )
}

GameObject *GameplayState::ReturnObject(unsigned int bucket, int index)
{
	return m_pObjects->ReturnObject(bucket, index);
}

GameObject* GameplayState::CreatePlayer(SGD::Point pos, string emitterName)
{
	player = new Player;

	if (emitterName != "")
	{
		player->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		player->GetEmitter()->SetObjectOwner(player);
	}

	player->SetPosition(pos);;
	player->SetVelocity(SGD::Vector{ 0, 0 });
	player->SetSize({ 64, 64 });
	player->SetColor({ 0, 0, 0 });
	//set start weapon
	GameObject* baseAugment = (CreateAugment(SGD::Point(-100, -100), "Arcane Shot"));
	ArcaneShot* temp = (ArcaneShot*)baseAugment;
	temp->SetAugType(1);
	player->SetStyleSlot((ArcaneShot*)baseAugment);
	m_pObjects->AddObject(baseAugment, AUGMENT_BUCKET);
	baseAugment->Release();
	baseAugment = nullptr;
	player->SetHealth(player->GetMaxHealth());
	return player;
}

GameObject* GameplayState::CreateProjectile(MovingObject * owner, float rotation, bool useFacing, string emitterName)
{
	Projectile * temp = new Projectile;

	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetOwner(owner);
	owner->AddRef();
	temp->SetColor({ 255, 0, 0 });
	temp->SetRangeMax(200);
	temp->SetRange(200);
	temp->SetDamage(2);
	temp->SetDoubleDamage(4);
	temp->SetRotation(rotation);

	if (dynamic_cast<Enemy *>(owner))
	{
		Enemy * tempenemy = (Enemy*)owner;
		Augment * tempaug = tempenemy->GetAugment();
		if (tempaug->GetAugName() == "Arcane Shot")
		{
			temp->SetBulletType(((ArcaneShot*)tempaug)->GetBulletType());
			temp->SetDamage(((ArcaneShot*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((ArcaneShot*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((ArcaneShot*)tempaug)->GetRange());
			temp->SetRange(((ArcaneShot*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetAttackRate(((ArcaneShot*)tempaug)->GetFireRate());
			tempenemy->SetDamage(((ArcaneShot*)tempaug)->GetDamage());
			tempenemy->SetBulletType(((ArcaneShot*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->ARCANESHOT);
		}
		else if (tempaug->GetAugName() == "Arcane Beam")
		{
			temp->SetBulletType(((ArcaneBeam*)tempaug)->GetBulletType());
			temp->SetDamage(((ArcaneBeam*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((ArcaneBeam*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((ArcaneBeam*)tempaug)->GetRange());
			temp->SetRange(((ArcaneBeam*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetAttackRate(((ArcaneBeam*)tempaug)->GetFireRate());
			tempenemy->SetDamage(((ArcaneBeam*)tempaug)->GetDamage());
			tempenemy->SetBulletType(((ArcaneBeam*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->BEAM);
		}
		else if (tempaug->GetAugName() == "Double Shot")
		{
			temp->SetBulletType(((DoubleShot*)tempaug)->GetBulletType());
			temp->SetDamage(((DoubleShot*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((DoubleShot*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((DoubleShot*)tempaug)->GetRange());
			temp->SetRange(((DoubleShot*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetAttackRate(((DoubleShot*)tempaug)->GetFireRate());
			tempenemy->SetDamage(((DoubleShot*)tempaug)->GetDamage());
			tempenemy->SetBulletType(((DoubleShot*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->DOUBLE);
		}
		else if (tempaug->GetAugName() == "Photon Shot")
		{
			temp->SetBulletType(((PhotonShot*)tempaug)->GetBulletType());
			temp->SetDamage(((PhotonShot*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((PhotonShot*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((PhotonShot*)tempaug)->GetRange());
			temp->SetRange(((PhotonShot*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((PhotonShot*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((PhotonShot*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((PhotonShot*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->PHOTON);
		}
		else if (tempaug->GetAugName() == "Vampiric Magnet")
		{
			temp->SetBulletType(((VampiricMagnet*)tempaug)->GetBulletType());
			temp->SetDamage(((VampiricMagnet*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((VampiricMagnet*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((VampiricMagnet*)tempaug)->GetRange());
			temp->SetRange(((VampiricMagnet*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((VampiricMagnet*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((VampiricMagnet*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((VampiricMagnet*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->VAMPIRIC);
		}
		else if (tempaug->GetAugName() == "Electron Shot")
		{
			temp->SetBulletType(((ElectronShot*)tempaug)->GetBulletType());
			temp->SetDamage(((ElectronShot*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((ElectronShot*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((ElectronShot*)tempaug)->GetRange());
			temp->SetRange(((ElectronShot*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((ElectronShot*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((ElectronShot*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((ElectronShot*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->ELECTRON);
		}
		else if (tempaug->GetAugName() == "Explosive")
		{
			temp->SetBulletType(((Explosive*)tempaug)->GetBulletType());
			temp->SetDamage(((Explosive*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((Explosive*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((Explosive*)tempaug)->GetRange());
			temp->SetRange(((Explosive*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((Explosive*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((Explosive*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((Explosive*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->EXPLOSIVE);
		}
		else if (tempaug->GetAugName() == "Fire Blast")
		{
			temp->SetBulletType(((FireBlast*)tempaug)->GetBulletType());
			temp->SetDamage(((FireBlast*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((FireBlast*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((FireBlast*)tempaug)->GetRange());
			temp->SetRange(((FireBlast*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetAttackRate(((FireBlast*)tempaug)->GetFireRate());
			tempenemy->SetDamage(((FireBlast*)tempaug)->GetDamage());
			tempenemy->SetBulletType(((FireBlast*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->FIREBLAST);
		}
		else if (tempaug->GetAugName() == "Shockwave")
		{
			temp->SetBulletType(((ShockWave*)tempaug)->GetBulletType());
			temp->SetDamage(((ShockWave*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((ShockWave*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((ShockWave*)tempaug)->GetRange());
			temp->SetRange(((ShockWave*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((ShockWave*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((ShockWave*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((ShockWave*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->SHOCKWAVE);
		}
		else if (tempaug->GetAugName() == "Solar Flare")
		{
			temp->SetBulletType(((SolarFlare*)tempaug)->GetBulletType());
			temp->SetDamage(((SolarFlare*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((SolarFlare*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((SolarFlare*)tempaug)->GetRange());
			temp->SetRange(((SolarFlare*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((SolarFlare*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((SolarFlare*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((SolarFlare*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->SOLARFLARE);
		}
		else if (tempaug->GetAugName() == "Magic Missile")
		{
			temp->SetBulletType(((MagicMissile*)tempaug)->GetBulletType());
			temp->SetDamage(((MagicMissile*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((MagicMissile*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((MagicMissile*)tempaug)->GetRange());
			temp->SetRange(((MagicMissile*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((MagicMissile*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((MagicMissile*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((MagicMissile*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->MAGICMISSILE);
		}
		else if (tempaug->GetAugName() == "Seeker Sludge")
		{
			temp->SetBulletType(((SeekerSludge*)tempaug)->GetBulletType());
			temp->SetDamage(((SeekerSludge*)tempaug)->GetDamage());
			temp->SetDoubleDamage(((SeekerSludge*)tempaug)->GetDamage() * 2);
			temp->SetRangeMax(((SeekerSludge*)tempaug)->GetRange());
			temp->SetRange(((SeekerSludge*)tempaug)->GetRange());
			temp->SetBulletSpeed(1.0f);
			tempenemy->SetDamage(((SeekerSludge*)tempaug)->GetDamage());
			tempenemy->SetAttackRate(((SeekerSludge*)tempaug)->GetFireRate());
			tempenemy->SetBulletType(((SeekerSludge*)tempaug)->GetBulletType());
			theGame->PlaySFX(theGame->SEEKER);
		}
		SGD::Vector tempVelocity = { 200.0f, 200.0f };
		if (useFacing)
		{
			tempVelocity.Rotate(rotation);
		}
		else
		{
			tempVelocity = { 0.0f, -1.0f };
			tempVelocity.Rotate(rotation);
			tempVelocity *= 200;
		}

		temp->SetVelocity(tempVelocity);
		temp->SetSize({ 16.0f, 16.0f });

		SGD::Point tempPosition = tempenemy->GetWeaponOffset();

		if (useFacing && owner->GetFacing() < 0)
			tempPosition.x -= owner->GetSize().width / 2;

		temp->SetPosition(tempPosition);
	}
	else if (owner->GetType() == MovingObject::OBJ_PLAYER)
	{
		if (player->GetStyleSlot() != nullptr)
		{
			Augment * Styletemp = player->GetStyleSlot();
			if (Styletemp->GetAugName() == "Arcane Shot")
			{
				temp->SetShotStyle(((ArcaneShot*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((ArcaneShot*)Styletemp)->GetRange());
				temp->SetRange(((ArcaneShot*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((ArcaneShot*)Styletemp)->GetBulletSpeed());
				if (player->GetBulletSlot() == nullptr)
				{

					temp->SetBulletType(((ArcaneShot*)Styletemp)->GetBulletType());
					temp->SetDamage(((ArcaneShot*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((ArcaneShot*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((ArcaneShot*)Styletemp)->GetFireRate());
					player->SetDamage(((ArcaneShot*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->ARCANESHOT);
				}

			}
			if (Styletemp->GetAugName() == "Arcane Beam")
			{
				temp->SetShotStyle(((ArcaneBeam*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((ArcaneBeam*)Styletemp)->GetRange());
				temp->SetRange(((ArcaneBeam*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((ArcaneBeam*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 0, 255, 0 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((ArcaneBeam*)Styletemp)->GetBulletType());
					temp->SetDamage(((ArcaneBeam*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((ArcaneBeam*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((ArcaneBeam*)Styletemp)->GetFireRate());
					player->SetDamage(((ArcaneBeam*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->BEAM);
				}
			}
			else if (Styletemp->GetAugName() == "Electron Shot")
			{
				temp->SetShotStyle(((ElectronShot*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((ElectronShot*)Styletemp)->GetRange());
				temp->SetRange(((ElectronShot*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((ElectronShot*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 255, 255, 0 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((ElectronShot*)Styletemp)->GetBulletType());
					temp->SetDamage(((ElectronShot*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((ElectronShot*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((ElectronShot*)Styletemp)->GetFireRate());
					player->SetDamage(((ElectronShot*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->ELECTRON);
				}
			}
			else if (Styletemp->GetAugName() == "Photon Shot")
			{
				temp->SetShotStyle(((PhotonShot*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((PhotonShot*)Styletemp)->GetRange());
				temp->SetRange(((PhotonShot*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((PhotonShot*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 255, 0, 255 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((PhotonShot*)Styletemp)->GetBulletType());
					temp->SetDamage(((PhotonShot*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((PhotonShot*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((PhotonShot*)Styletemp)->GetFireRate());
					player->SetDamage(((PhotonShot*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->PHOTON);
				}
			}
			else if (Styletemp->GetAugName() == "Vampiric Magnet")
			{
				temp->SetShotStyle(((VampiricMagnet*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((VampiricMagnet*)Styletemp)->GetRange());
				temp->SetRange(((VampiricMagnet*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((VampiricMagnet*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 255, 255, 255 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((VampiricMagnet*)Styletemp)->GetBulletType());
					temp->SetDamage(((VampiricMagnet*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((VampiricMagnet*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((VampiricMagnet*)Styletemp)->GetFireRate());
					player->SetDamage(((VampiricMagnet*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->VAMPIRIC);
				}
			}
			else if (Styletemp->GetAugName() == "Double Shot")
			{
				temp->SetShotStyle(((DoubleShot*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((DoubleShot*)Styletemp)->GetRange());
				temp->SetRange(((DoubleShot*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((DoubleShot*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 0, 255, 255 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((DoubleShot*)Styletemp)->GetBulletType());
					temp->SetDamage(((DoubleShot*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((DoubleShot*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((DoubleShot*)Styletemp)->GetFireRate());
					player->SetDamage(((DoubleShot*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->DOUBLE);
				}
			}
			else if (Styletemp->GetAugName() == "Shockwave")
			{
				temp->SetShotStyle(((ShockWave*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((ShockWave*)Styletemp)->GetRange());
				temp->SetRange(((ShockWave*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((ShockWave*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 0, 0, 255 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((ShockWave*)Styletemp)->GetBulletType());
					temp->SetDamage(((ShockWave*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((ShockWave*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((ShockWave*)Styletemp)->GetFireRate());
					player->SetDamage(((ShockWave*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->SHOCKWAVE);
				}
			}
			else if (Styletemp->GetAugName() == "Fire Blast")
			{
				temp->SetShotStyle(((FireBlast*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((FireBlast*)Styletemp)->GetRange());
				temp->SetRange(((FireBlast*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((FireBlast*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 205, 50, 50 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((FireBlast*)Styletemp)->GetBulletType());
					temp->SetDamage(((FireBlast*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((FireBlast*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((FireBlast*)Styletemp)->GetFireRate());
					player->SetDamage(((FireBlast*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->FIREBLAST);
				}
			}
			else if (Styletemp->GetAugName() == "Explosive")
			{
				temp->SetShotStyle(((Explosive*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((Explosive*)Styletemp)->GetRange());
				temp->SetRange(((Explosive*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((Explosive*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 100, 100, 255 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((Explosive*)Styletemp)->GetBulletType());
					temp->SetDamage(((Explosive*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((Explosive*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((Explosive*)Styletemp)->GetFireRate());
					player->SetDamage(((Explosive*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->EXPLOSIVE);
				}
			}
			else if (Styletemp->GetAugName() == "Solar Flare")
			{
				temp->SetShotStyle(((SolarFlare*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((SolarFlare*)Styletemp)->GetRange());
				temp->SetRange(((SolarFlare*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((SolarFlare*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 100, 255, 0 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((SolarFlare*)Styletemp)->GetBulletType());
					temp->SetDamage(((SolarFlare*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((SolarFlare*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((SolarFlare*)Styletemp)->GetFireRate());
					player->SetDamage(((SolarFlare*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->SOLARFLARE);
				}
			}
			else if (Styletemp->GetAugName() == "Seeker Sludge")
			{
				temp->SetShotStyle(((SeekerSludge*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((SeekerSludge*)Styletemp)->GetRange());
				temp->SetRange(((SeekerSludge*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((SeekerSludge*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 25, 25, 25 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((SeekerSludge*)Styletemp)->GetBulletType());
					temp->SetDamage(((SeekerSludge*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((SeekerSludge*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((SeekerSludge*)Styletemp)->GetFireRate());
					player->SetDamage(((SeekerSludge*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->SEEKER);
				}
			}
			else if (Styletemp->GetAugName() == "Magic Missile")
			{

				temp->SetShotStyle(((MagicMissile*)Styletemp)->GetShotStyle());
				temp->SetRangeMax(((MagicMissile*)Styletemp)->GetRange());
				temp->SetRange(((MagicMissile*)Styletemp)->GetRange());
				temp->SetBulletSpeed(((MagicMissile*)Styletemp)->GetBulletSpeed());
				temp->SetColor({ 150, 255, 55 });
				if (player->GetBulletSlot() == nullptr)
				{
					temp->SetBulletType(((MagicMissile*)Styletemp)->GetBulletType());
					temp->SetDamage(((MagicMissile*)Styletemp)->GetDamage());
					temp->SetDoubleDamage(((MagicMissile*)Styletemp)->GetDamage() * 2);
					player->SetAttackRate(((MagicMissile*)Styletemp)->GetFireRate());
					player->SetDamage(((MagicMissile*)Styletemp)->GetDamage());
					theGame->PlaySFX(theGame->MAGICMISSILE);
				}
			}
		}
		if (player->GetBulletSlot() != nullptr)
		{
			Augment* augtemp = player->GetBulletSlot();
			if (augtemp->GetAugName() == "Arcane Shot")
			{
				temp->SetBulletType(((ArcaneShot*)augtemp)->GetBulletType());
				temp->SetDamage(((ArcaneShot*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((ArcaneShot*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((ArcaneShot*)augtemp)->GetFireRate());
				player->SetDamage(((ArcaneShot*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((ArcaneShot*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((ArcaneShot*)augtemp)->GetRange());
					temp->SetRange(((ArcaneShot*)augtemp)->GetRange());
					temp->SetBulletSpeed(((ArcaneShot*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->ARCANESHOT);
			}
			else if (augtemp->GetAugName() == "Arcane Beam")//needs else ifs instead of a bunch of ifs
			{
				temp->SetBulletType(((ArcaneBeam*)augtemp)->GetBulletType());
				temp->SetDamage(((ArcaneBeam*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((ArcaneBeam*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((ArcaneBeam*)augtemp)->GetFireRate());
				player->SetDamage(((ArcaneBeam*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((ArcaneBeam*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((ArcaneBeam*)augtemp)->GetRange());
					temp->SetRange(((ArcaneBeam*)augtemp)->GetRange());
					temp->SetBulletSpeed(((ArcaneBeam*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->BEAM);
			}
			else if (augtemp->GetAugName() == "Electron Shot")
			{
				temp->SetBulletType(((ElectronShot*)augtemp)->GetBulletType());
				temp->SetDamage(((ElectronShot*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((ElectronShot*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((ElectronShot*)augtemp)->GetFireRate());
				player->SetDamage(((ElectronShot*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((ElectronShot*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((ElectronShot*)augtemp)->GetRange());
					temp->SetRange(((ElectronShot*)augtemp)->GetRange());
					temp->SetBulletSpeed(((ElectronShot*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->ELECTRON);
			}
			else if (augtemp->GetAugName() == "Photon Shot")
			{
				temp->SetBulletType(((PhotonShot*)augtemp)->GetBulletType());
				temp->SetDamage(((PhotonShot*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((PhotonShot*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((PhotonShot*)augtemp)->GetFireRate());
				player->SetDamage(((PhotonShot*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((PhotonShot*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((PhotonShot*)augtemp)->GetRange());
					temp->SetRange(((PhotonShot*)augtemp)->GetRange());
					temp->SetBulletSpeed(((PhotonShot*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->PHOTON);
			}
			else if (augtemp->GetAugName() == "Vampiric Magnet")
			{
				temp->SetBulletType(((VampiricMagnet*)augtemp)->GetBulletType());
				temp->SetDoubleDamage(((VampiricMagnet*)augtemp)->GetDamage() * 2);
				temp->SetDamage(((VampiricMagnet*)augtemp)->GetDamage());
				player->SetAttackRate(((VampiricMagnet*)augtemp)->GetFireRate());
				player->SetDamage(((VampiricMagnet*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
					temp->SetShotStyle(((VampiricMagnet*)augtemp)->GetShotStyle());
				theGame->PlaySFX(theGame->VAMPIRIC);
			}
			else if (augtemp->GetAugName() == "Double Shot")
			{
				temp->SetBulletType(((DoubleShot*)augtemp)->GetBulletType());
				temp->SetDoubleDamage(((DoubleShot*)augtemp)->GetDamage() * 2);
				temp->SetDamage(((DoubleShot*)augtemp)->GetDamage());
				player->SetAttackRate(((DoubleShot*)augtemp)->GetFireRate());
				player->SetDamage(((DoubleShot*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((DoubleShot*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((DoubleShot*)augtemp)->GetRange());
					temp->SetRange(((DoubleShot*)augtemp)->GetRange());
					temp->SetBulletSpeed(((DoubleShot*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->DOUBLE);
			}
			else if (augtemp->GetAugName() == "Shockwave")
			{
				temp->SetBulletType(((ShockWave*)augtemp)->GetBulletType());
				temp->SetDamage(((ShockWave*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((ShockWave*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((ShockWave*)augtemp)->GetFireRate());
				player->SetDamage(((ShockWave*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((ShockWave*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((ShockWave*)augtemp)->GetRange());
					temp->SetRange(((ShockWave*)augtemp)->GetRange());
					temp->SetBulletSpeed(((ShockWave*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->SHOCKWAVE);
			}
			else if (augtemp->GetAugName() == "Fire Blast")
			{
				temp->SetBulletType(((FireBlast*)augtemp)->GetBulletType());
				temp->SetDamage(((FireBlast*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((FireBlast*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((FireBlast*)augtemp)->GetFireRate());
				theGame->PlaySFX(theGame->FIREBLAST);
				player->SetDamage(((FireBlast*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((FireBlast*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((FireBlast*)augtemp)->GetRange());
					temp->SetRange(((FireBlast*)augtemp)->GetRange());
					temp->SetBulletSpeed(((FireBlast*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->FIREBLAST);
			}
			else if (augtemp->GetAugName() == "Solar Flare")
			{
				temp->SetBulletType(((SolarFlare*)augtemp)->GetBulletType());
				temp->SetDamage(((SolarFlare*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((SolarFlare*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((SolarFlare*)augtemp)->GetFireRate());
				player->SetDamage(((SolarFlare*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((SolarFlare*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((SolarFlare*)augtemp)->GetRange());
					temp->SetRange(((SolarFlare*)augtemp)->GetRange());
					temp->SetBulletSpeed(((SolarFlare*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->SOLARFLARE);
			}
			else if (augtemp->GetAugName() == "Explosive")
			{
				temp->SetBulletType(((Explosive*)augtemp)->GetBulletType());
				temp->SetDamage(((Explosive*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((Explosive*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((Explosive*)augtemp)->GetFireRate());
				player->SetDamage(((Explosive*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((Explosive*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((Explosive*)augtemp)->GetRange());
					temp->SetRange(((Explosive*)augtemp)->GetRange());
					temp->SetBulletSpeed(((Explosive*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->EXPLOSIVE);
			}
			else if (augtemp->GetAugName() == "Seeker Sludge")
			{
				temp->SetBulletType(((SeekerSludge*)augtemp)->GetBulletType());
				temp->SetDamage(((SeekerSludge*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((SeekerSludge*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((SeekerSludge*)augtemp)->GetFireRate());
				player->SetDamage(((SeekerSludge*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((SeekerSludge*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((SeekerSludge*)augtemp)->GetRange());
					temp->SetRange(((SeekerSludge*)augtemp)->GetRange());
					temp->SetBulletSpeed(((SeekerSludge*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->SEEKER);
			}
			else if (augtemp->GetAugName() == "Magic Missile")
			{
				temp->SetBulletType(((MagicMissile*)augtemp)->GetBulletType());
				temp->SetDamage(((MagicMissile*)augtemp)->GetDamage());
				temp->SetDoubleDamage(((MagicMissile*)augtemp)->GetDamage() * 2);
				player->SetAttackRate(((MagicMissile*)augtemp)->GetFireRate());
				player->SetDamage(((MagicMissile*)augtemp)->GetDamage());
				if (player->GetStyleSlot() == nullptr)
				{
					temp->SetShotStyle(((MagicMissile*)augtemp)->GetShotStyle());
					temp->SetRangeMax(((MagicMissile*)augtemp)->GetRange());
					temp->SetRange(((MagicMissile*)augtemp)->GetRange());
					temp->SetBulletSpeed(((MagicMissile*)augtemp)->GetBulletSpeed());
				}
				theGame->PlaySFX(theGame->MAGICMISSILE);
			}

		}

		SGD::Vector tempVelocity = { 200, 200 };
		if (useFacing)
		{
			temp->SetVelocity(dynamic_cast<Player*>(owner)->GetAiming());
		}
		else
		{
			tempVelocity = { 0, -1 };
			tempVelocity.Rotate(rotation);
			temp->SetVelocity(SGD::InputManager::GetInstance()->GetLeftJoystick(0));
		}

		temp->SetSize({ 16, 16 });

		SGD::Point tempPosition = SGD::Point(owner->GetWeaponOffset().x, owner->GetWeaponOffset().y);

		temp->SetOwnerVel((float)(player->GetVelocity().x));
		temp->SetPosition(tempPosition);
	}

	return temp;
}

void GameplayState::HUD()
{
	SGD::GraphicsManager* pGraphics = SGD::GraphicsManager::GetInstance();

	SGD::Point hudPosition = { 50, 40 };
	SGD::Point hudOffset = { 22, 20 };

	SGD::Rectangle healthbar;
	healthbar.left = hudPosition.x + hudOffset.x;
	healthbar.top = hudPosition.y + hudOffset.y;
	healthbar.right = healthbar.left + 193;
	healthbar.bottom = healthbar.top + 10;

	SGD::Rectangle health;
	health.left = healthbar.left;
	health.top = healthbar.top;
	health.right = healthbar.left + healthbar.ComputeWidth() * ((float)player->GetHealth() / (player->GetMaxHealth()));
	health.bottom = health.top + 10;

	SGD::Rectangle style;
	style.left = healthbar.left + 5;
	style.top = healthbar.top + 30;
	style.right = style.left + (20);
	style.bottom = style.top + (20);
	if (player->GetStyleSlot() != nullptr)
		pGraphics->DrawTexture(player->GetStyleSlot()->GetImage(), { style.left, style.top });

	SGD::Rectangle bullet;
	bullet.left = style.right + 5;
	bullet.top = healthbar.top + 30;
	bullet.right = bullet.left + (20);
	bullet.bottom = bullet.top + (20);
	if (player->GetBulletSlot() != nullptr)
		pGraphics->DrawTexture(player->GetBulletSlot()->GetImage(), { bullet.left, bullet.top });

	SGD::Rectangle movement;
	movement.left = bullet.right + 5;
	movement.top = healthbar.top + 30;
	movement.right = movement.left + (20);
	movement.bottom = movement.top + (20);
	if (player->GetMoveSlot() != nullptr)
	{
		//display the image of the currently equipped augmentation gem
		pGraphics->DrawTexture(player->GetMoveSlot()->GetImage(), { movement.left, movement.top });

		//display the cooldown for the current augmentation gem
		if (player->GetMoveSlot()->GetType() == Movement::MOVE_DASH)
			HUDCoolDowns(player->GetMaxDashCD(), player->GetDashCoolDown(), player->GetMoveSlot()->GetImage(), movement);
		else if (player->GetMoveSlot()->GetType() == Movement::MOVE_BACKDASH)
			HUDCoolDowns(player->GetMaxBackDashCD(), player->GetBackDashCoolDown(), player->GetMoveSlot()->GetImage(), movement);
		else if (player->GetMoveSlot()->GetType() == Movement::MOVE_SLIDE)
			HUDCoolDowns(player->GetMaxSlideCD(), player->GetSlideCoolDown(), player->GetMoveSlot()->GetImage(), movement);
	}


	SGD::Rectangle hotswap;
	hotswap.left = Game::GetInstance()->GetScreenWidth() / 20;
	hotswap.bottom = Game::GetInstance()->GetScreenHeight() - Game::GetInstance()->GetScreenHeight() / 20;
	hotswap.right = hotswap.left + (32);
	hotswap.top = hotswap.bottom - 32;

	Augment* hotSwapIndex[4];

	hotSwapIndex[0] = player->GetHotSwap(0);
	if (hotSwapIndex[0] != nullptr)
	{
		pGraphics->DrawTexture(hotSwapIndex[0]->GetImage(), { hotswap.left + 5, hotswap.top - 32 });
		if (hotSwapIndex[0]->GetType() == Movement::MOVE_DASH)
			HUDCoolDowns(player->GetMaxDashCD(), player->GetDashCoolDown(), hotSwapIndex[0]->GetImage(), SGD::Rectangle(hotswap.left, hotswap.top - 32, hotswap.left + 20, hotswap.top - 12));
		else if (hotSwapIndex[0]->GetType() == Movement::MOVE_BACKDASH)
			HUDCoolDowns(player->GetMaxBackDashCD(), player->GetBackDashCoolDown(), hotSwapIndex[0]->GetImage(), SGD::Rectangle(hotswap.left, hotswap.top - 32, hotswap.left + 20, hotswap.top - 12));
		else if (hotSwapIndex[0]->GetType() == Movement::MOVE_SLIDE)
			HUDCoolDowns(player->GetMaxSlideCD(), player->GetSlideCoolDown(), hotSwapIndex[0]->GetImage(), SGD::Rectangle(hotswap.left, hotswap.top - 32, hotswap.left + 20, hotswap.top - 12));
	}

	hotSwapIndex[1] = player->GetHotSwap(1);
	if (hotSwapIndex[1] != nullptr)
	{
		pGraphics->DrawTexture(hotSwapIndex[1]->GetImage(), { hotswap.right, hotswap.top });
		if (hotSwapIndex[1]->GetType() == Movement::MOVE_DASH)
			HUDCoolDowns(player->GetMaxDashCD(), player->GetDashCoolDown(), hotSwapIndex[1]->GetImage(), SGD::Rectangle(hotswap.right, hotswap.top, hotswap.right + 20, hotswap.top + 20));
		else if (hotSwapIndex[1]->GetType() == Movement::MOVE_BACKDASH)
			HUDCoolDowns(player->GetMaxBackDashCD(), player->GetBackDashCoolDown(), hotSwapIndex[1]->GetImage(), SGD::Rectangle(hotswap.right, hotswap.top, hotswap.right + 20, hotswap.top + 20));
		else if (hotSwapIndex[1]->GetType() == Movement::MOVE_SLIDE)
			HUDCoolDowns(player->GetMaxSlideCD(), player->GetSlideCoolDown(), hotSwapIndex[1]->GetImage(), SGD::Rectangle(hotswap.right, hotswap.top, hotswap.right + 20, hotswap.top + 20));
	}

	hotSwapIndex[2] = player->GetHotSwap(2);
	if (hotSwapIndex[2] != nullptr)
	{
		pGraphics->DrawTexture(hotSwapIndex[2]->GetImage(), { hotswap.left + 5, hotswap.bottom });
		if (hotSwapIndex[2]->GetType() == Movement::MOVE_DASH)
			HUDCoolDowns(player->GetMaxDashCD(), player->GetDashCoolDown(), hotSwapIndex[2]->GetImage(), SGD::Rectangle(hotswap.left, hotswap.bottom, hotswap.left + 20, hotswap.bottom + 20));
		else if (hotSwapIndex[2]->GetType() == Movement::MOVE_BACKDASH)
			HUDCoolDowns(player->GetMaxBackDashCD(), player->GetBackDashCoolDown(), hotSwapIndex[2]->GetImage(), SGD::Rectangle(hotswap.left, hotswap.bottom, hotswap.left + 20, hotswap.bottom + 20));
		else if (hotSwapIndex[2]->GetType() == Movement::MOVE_SLIDE)
			HUDCoolDowns(player->GetMaxSlideCD(), player->GetSlideCoolDown(), hotSwapIndex[2]->GetImage(), SGD::Rectangle(hotswap.left, hotswap.bottom, hotswap.left + 20, hotswap.bottom + 20));
	}

	hotSwapIndex[3] = player->GetHotSwap(3);
	if (hotSwapIndex[3] != nullptr)
	{
		pGraphics->DrawTexture(hotSwapIndex[3]->GetImage(), { hotswap.left - 32, hotswap.top });
		if (hotSwapIndex[3]->GetType() == Movement::MOVE_DASH)
			HUDCoolDowns(player->GetMaxDashCD(), player->GetDashCoolDown(), hotSwapIndex[3]->GetImage(), SGD::Rectangle(hotswap.left - 32, hotswap.top, hotswap.left - 12, hotswap.top + 20));
		else if (hotSwapIndex[3]->GetType() == Movement::MOVE_BACKDASH)
			HUDCoolDowns(player->GetMaxBackDashCD(), player->GetBackDashCoolDown(), hotSwapIndex[3]->GetImage(), SGD::Rectangle(hotswap.left - 32, hotswap.top, hotswap.left - 12, hotswap.top + 20));
		else if (hotSwapIndex[3]->GetType() == Movement::MOVE_SLIDE)
			HUDCoolDowns(player->GetMaxSlideCD(), player->GetSlideCoolDown(), hotSwapIndex[3]->GetImage(), SGD::Rectangle(hotswap.left - 32, hotswap.top, hotswap.left - 12, hotswap.top + 20));
	}

	//draw the outline for the max healthbar
	SGD::GraphicsManager::GetInstance()->DrawRectangle(healthbar, { 0, 0, 0, 0 }, { 255, 0, 0, 0 });

	//check which color the helath bar of the boss should be rendered as based on the amount of hp missing
	if ((float)player->GetHealth() / player->GetMaxHealth() >= 3.0f / 4.0f)
		SGD::GraphicsManager::GetInstance()->DrawRectangle(health, { 0, 255, 0 });//display green if its over 3/4 of the player's maxhp
	else if ((float)player->GetHealth() / player->GetMaxHealth() >= 1.0f / 2.0f)
		SGD::GraphicsManager::GetInstance()->DrawRectangle(health, { 255, 255, 0 });//display yellow if its below 3/4 of the player's maxhp and above 1/2 of the player's max hp
	else if ((float)player->GetHealth() / player->GetMaxHealth() >= 1.0f / 4.0f)
		SGD::GraphicsManager::GetInstance()->DrawRectangle(health, { 255, 140, 0 });//display orange if its below 1/2 of the player's maxhp and above 1/4 of the player's max hp
	else
		SGD::GraphicsManager::GetInstance()->DrawRectangle(health, { 255, 0, 0 });//display red if its below 1/4 the player's max hp

	SGD::GraphicsManager::GetInstance()->DrawTextureSection(dpad, { hotswap.left, hotswap.top }, { 13, 33, 83, 104 }, {}, {}, {}, { 0.5f, 0.5f });

	pGraphics->DrawTexture(hudImage, hudPosition);

	std::ostringstream ossScore;
	std::ostringstream ossCombo;
	ossCombo.fill('0');
	ossScore.fill('0');

	int score = player->GetScore();
	int combomult = player->GetComboMult();
	ossScore << std::setw(7) << score;
	ossCombo << "Combo x" << combomult;
	if (currLevel != 3)
	{
		Game::GetInstance()->GetFont()->Draw(ossCombo.str().c_str(), 600, 50, .5f, { 255, 255, 255 });
		Game::GetInstance()->GetFont()->Draw(ossScore.str().c_str(), int(Game::GetInstance()->GetScreenWidth() - (7 * 32)) / 2, int(Game::GetInstance()->GetScreenHeight() / 20), 1.0f, { 255, 255, 255 });

	}
	else if (currLevel == 3)
	{
		Game::GetInstance()->GetFont()->Draw(ossCombo.str().c_str(), 600, 50, .5f, { 0, 0, 0 });
		Game::GetInstance()->GetFont()->Draw(ossScore.str().c_str(), int(Game::GetInstance()->GetScreenWidth() - (7 * 32)) / 2, int(Game::GetInstance()->GetScreenHeight() / 20), 1.0f, { 0,0,0 });
	}

}

void GameplayState::HUDCoolDowns(float cd, float currCD, SGD::HTexture image, SGD::Rectangle position)
{
	//TODO fix jumpiness of feed back for abilities' cooldowns
	SGD::GraphicsManager* pGraphics = SGD::GraphicsManager::GetInstance();
	SGD::Rectangle theCoolDown = SGD::Rectangle(0, 20 - position.ComputeHeight() * (currCD / cd), 20, 20);
	pGraphics->DrawTextureSection(image, { position.left, position.top + position.ComputeHeight() * ((cd - currCD) / cd) }, theCoolDown, {}, {}, { 255, 100, 100, 100 });
}

GameObject* GameplayState::CreatePortal(int level, SGD::Point position, string emitterName)
{
	Portal* temp = new Portal();

	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetType(PortalType::PORTAL_LOADLEVEL);
	temp->SetLevel(level);
	temp->SetPosition(position);
	temp->SetVelocity({ 0, 0 });
	temp->SetGravityState(true);
	return temp;
}

GameObject* GameplayState::CreatePortal(SGD::Point warpLoc, SGD::Point position, string emitterName)
{
	Portal* temp = new Portal();

	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetType(PortalType::PORTAL_HIDDENAREA);
	temp->SetWarpLoc(warpLoc);
	temp->SetPosition(position);
	temp->SetGravityState(true);
	return temp;
}

GameObject* GameplayState::CreatePortal(SGD::Point position, string emitterName)
{
	Portal* temp = new Portal();

	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetType(PortalType::PORTAL_PLAYERLEVEL);
	temp->SetPosition(position);
	temp->SetGravityState(true);
	return temp;
}

GameObject* GameplayState::CreateLadder(SGD::Point pos, string emitterName)
{
	Ladder* temp = new Ladder();
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	return temp;
}

GameObject* GameplayState::CreateStairs(SGD::Point pos, string emitterName)
{
	Stairs* temp = new Stairs();
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	return temp;
}

void GameplayState::SetLevel(int level)
{
	if (level > -1)
	{
		if (!m_pObjects->IsEmpty(ObjBuckets::ENEMY_BULLET_BUCKET))
			m_pObjects->RemoveAllFromBucket(ObjBuckets::ENEMY_BULLET_BUCKET);
		if (!m_pObjects->IsEmpty(ObjBuckets::PLAYER_BULLET_BUCKET))
			m_pObjects->RemoveAllFromBucket(ObjBuckets::PLAYER_BULLET_BUCKET);
		if (!m_pObjects->IsEmpty(ObjBuckets::AUGMENT_BUCKET))
			m_pObjects->CleanUpAugments();
		if (!m_pObjects->IsEmpty(ObjBuckets::ENEMY_BUCKET))
			m_pObjects->RemoveAllFromBucket(ObjBuckets::ENEMY_BUCKET);
		if (!m_pObjects->IsEmpty(ObjBuckets::OBJ_BUCKET))
			m_pObjects->RemoveAllFromBucket(ObjBuckets::OBJ_BUCKET);
		if (!m_pObjects->IsEmpty(ObjBuckets::PORTAL_BUCKET))
			m_pObjects->RemoveAllFromBucket(ObjBuckets::PORTAL_BUCKET);

		pAudio->StopAudio(Game::GetInstance()->GetSong(currLevel));
		if (!pAudio->IsAudioPlaying(Game::GetInstance()->GetSong(level)))
			pAudio->PlayAudio(Game::GetInstance()->GetSong(level), true);
		else if (!pAudio->IsAudioPlaying(Game::GetInstance()->GetSong(level)))
			pAudio->PlayAudio(Game::GetInstance()->GetSong(5), true);

		currLevel = level;

		if (player != nullptr)
		{
			player->SetMinPosInWorld(0.0f);
			player->SetHealth(player->GetMaxHealth());
			player->ClearDebuffs();
		}

		switch (level)
		{
		case 0:
		{
			if (player != nullptr)
			{
				SavePlayerFile(LoadGameState::GetInstance()->GetFile());
			}
			TS->StartLevel(level);
			mapIndex = 0;
		}
			break;
		case 1:
		{
			if (levelOne == 0)
			{
				levelOne = TS->Load("./resource/Levels/", "forest.xml");
			}
			TS->StartLevel(levelOne);
			mapIndex = levelOne;
		}
			break;
		case 2:
		{
			if (levelTwo == 0)
			{
				levelTwo = TS->Load("./resource/Levels/", "cave.xml");
			}
			TS->StartLevel(levelTwo);
			mapIndex = levelTwo;
		}
			break;
		case 3:
		{
			if (levelThree == 0)
			{
				levelThree = TS->Load("./resource/Levels/", "castle.xml");
			}
			TS->StartLevel(levelThree);
			mapIndex = levelThree;
		}
			break;
		case 4:
		{
			if (levelFour == 0)
			{
				levelFour = TS->Load("./resource/Levels/", "volcano.xml");
			}
			TS->StartLevel(levelFour);
			mapIndex = levelFour;
		}
			break;
		default:
		{
			mapIndex = level - 4;
			TS->StartLevel(mapIndex);
		}
			break;
		}
	}
}

GameObject* GameplayState::CreateGoblin(SGD::Point pos, string emitterName)
{
	Goblin * temp = new Goblin;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -15 });
	temp->SetSize({ 64, 64 });
	temp->SetColor({ 255, 0, 255 });
	temp->SetDamage(15);
	temp->SetHealth(125);
	temp->SetMaxHealth(125);

	return temp;
}

GameObject* GameplayState::CreateKnight(SGD::Point pos, string emitterName)
{
	Knight * temp = new Knight;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(12);
	temp->SetHealth(100);
	temp->SetMaxHealth(100);
	return temp;
}

GameObject* GameplayState::CreateBat(SGD::Point pos, bool vampire, string emitterName)
{
	Bat * temp = new Bat;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });

	if (vampire)
		temp->SetDamage(15);
	else
		temp->SetDamage(10);
	temp->SetHealth(1);
	temp->SetMaxHealth(1);
	return temp;
}

GameObject* GameplayState::CreateElf(SGD::Point pos, string emitterName)
{
	Elf * temp = new Elf;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(10);
	temp->SetHealth(75);
	temp->SetMaxHealth(75);
	temp->SetAugment(RandomizeAugment());
	return temp;
}

GameObject* GameplayState::CreateArcher(SGD::Point pos, string emitterName)
{
	Archer * temp = new Archer;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(10);
	temp->SetHealth(75);
	temp->SetMaxHealth(75);

	temp->SetAugment(RandomizeAugment());
	return temp;
}

GameObject* GameplayState::CreateSpider(SGD::Point pos, string emitterName)
{
	Spider * temp = new Spider;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(10);
	temp->SetHealth(50);
	temp->SetMaxHealth(50);
	return temp;
}

GameObject* GameplayState::CreateOgre(SGD::Point pos, string emitterName)
{
	Ogre * temp = new Ogre;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, 0 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(40);
	temp->SetHealth(550);
	temp->SetMaxHealth(550);

	temp->SetAugment(RandomizeAugment());
	return temp;
}

GameObject* GameplayState::CreateGiantSpider(SGD::Point pos, string emitterName)
{
	GiantSpider * temp = new GiantSpider;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(30);
	temp->SetHealth(400);
	temp->SetMaxHealth(400);

	temp->SetAugment(RandomizeAugment());
	return temp;
}

GameObject* GameplayState::CreateVampire(SGD::Point pos, string emitterName)
{
	Vampire * temp = new Vampire;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(35);
	temp->SetHealth(550);
	temp->SetMaxHealth(550);

	temp->SetAugment(RandomizeAugment());
	return temp;
}

GameObject* GameplayState::CreateDragon(SGD::Point pos, string emitterName)
{
	Dragon * temp = new Dragon;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, -25 });
	temp->SetSize({ 128, 128 });
	temp->SetColor({ 0, 0, 0 });
	temp->SetDamage(45);
	temp->SetHealth(600);
	temp->SetMaxHealth(600);

	temp->SetAugment(RandomizeAugment());
	return temp;
}

GameObject* GameplayState::CreateHealthPickup(SGD::Point pos, string emitterName)
{
	Health * temp = new Health;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, 0 });
	temp->SetSize({ 32, 32 });
	temp->SetPickupType(Pickup::PICK_HP);
	temp->SetGravityState(true);
	return temp;
}

GameObject* GameplayState::CreateShieldPickup(SGD::Point pos, string emitterName)
{
	Shield * temp = new Shield;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, 0 });
	temp->SetSize({ 32, 32 });
	temp->SetShieldStatus(true);
	temp->SetPickupType(Pickup::PICK_SHIELD);
	temp->SetGravityState(true);
	return temp;
}

void GameplayState::LoadUCC()
{
	uccList.clear();

	WIN32_FIND_DATA FindFileData;
	HANDLE hFind;

	wchar_t my_documents[MAX_PATH];
	HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
	lstrcat(my_documents, L"\\MegaLands\\*");

	hFind = FindFirstFile(my_documents, &FindFileData);
	do {
		// ignore directories 
		if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
		{
			wstring name = FindFileData.cFileName;
			if (name[name.find_last_of(L".") + 1] == 'x') //Is it an xml? 
			{
				char newName[128];
				wcstombs_s(nullptr, newName, name.c_str(), name.length());
				newName[name.length()] = '\0';

				string truncName = newName;
				truncName.erase(truncName.find_first_of("."));

				uccList.push_back(truncName);
			}
		}
	} while (FindNextFile(hFind, &FindFileData) != 0);
}

GameObject* GameplayState::CreateAugmentTable(SGD::Point pos, int tabletype, string emitterName)
{
	AugmentTable * temp = new AugmentTable;
	if (emitterName != "")
	{
		temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
		temp->GetEmitter()->SetObjectOwner(temp);
	}

	temp->SetPosition(pos);
	temp->SetVelocity({ 0, 0 });
	temp->SetSize({ 48, 40 });
	temp->SetTabletype(tabletype);
	temp->SetGravityState(false);
	return temp;
}

GameObject* GameplayState::CreateAugment(SGD::Point pos, std::string name, string emitterName)
{
	if (name == "Arcane Shot")
	{
		ArcaneShot * temp = new ArcaneShot;
		if (emitterName != "")
		{
			temp->SetEmitter(new Emitter(particleSystem->GetEmitterMap()[emitterName]));
			temp->GetEmitter()->SetObjectOwner(temp);
		}

		temp->SetAugName(name);
		temp->SetDamage(25);
		temp->SetBulletSpeed(500);
		temp->SetRange(300);
		temp->SetFireRate(.2f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Arcane Beam")
	{
		ArcaneBeam * temp = new ArcaneBeam;
		temp->SetAugName(name);
		temp->SetDamage(25);
		temp->SetBulletSpeed(1200);
		temp->SetRange(500);
		temp->SetFireRate(.1f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Double Shot")
	{
		DoubleShot * temp = new DoubleShot;
		temp->SetAugName(name);
		temp->SetDamage(50);
		temp->SetBulletSpeed(800);
		temp->SetRange(300);
		temp->SetFireRate(.5f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Electron Shot")
	{
		ElectronShot * temp = new ElectronShot;
		temp->SetAugName(name);
		temp->SetDamage(60);
		temp->SetBulletSpeed(600);
		temp->SetRange(1250);
		temp->SetFireRate(.7f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Explosive")
	{
		Explosive * temp = new Explosive;
		temp->SetAugName(name);
		temp->SetDamage(100);
		temp->SetBulletSpeed(900);
		temp->SetRange(600);
		temp->SetFireRate(1.1f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Fire Blast")
	{
		FireBlast * temp = new FireBlast;
		temp->SetAugName(name);
		temp->SetDamage(60);
		temp->SetBulletSpeed(400);
		temp->SetRange(400);
		temp->SetFireRate(.5f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Magic Missile")
	{
		MagicMissile * temp = new MagicMissile;
		temp->SetAugName(name);
		temp->SetDamage(120);
		temp->SetBulletSpeed(1000);
		temp->SetRange(1200);
		temp->SetFireRate(.7f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Photon Shot")
	{
		PhotonShot * temp = new PhotonShot;
		temp->SetAugName(name);
		temp->SetDamage(60);
		temp->SetBulletSpeed(1000);
		temp->SetRange(1200);
		temp->SetFireRate(.7f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Seeker Sludge")
	{
		SeekerSludge * temp = new SeekerSludge;
		temp->SetAugName(name);
		temp->SetDamage(60);
		temp->SetBulletSpeed(750);
		temp->SetRange(550);
		temp->SetFireRate(.8f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Shockwave")
	{
		ShockWave * temp = new ShockWave;
		temp->SetAugName(name);
		temp->SetDamage(75);
		temp->SetBulletSpeed(900);
		temp->SetRange(1400);
		temp->SetFireRate(1.5f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Solar Flare")
	{
		SolarFlare * temp = new SolarFlare;
		temp->SetAugName(name);
		temp->SetDamage(75);
		temp->SetBulletSpeed(900);
		temp->SetRange(1700);
		temp->SetFireRate(1.6f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Vampiric Magnet")
	{
		VampiricMagnet * temp = new VampiricMagnet;
		temp->SetAugName(name);
		temp->SetDamage(55);
		temp->SetBulletSpeed(600);
		temp->SetRange(300);
		temp->SetFireRate(.8f);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Back Dash")
	{
		BackDash * temp = new BackDash;
		temp->SetAugName(name);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Dash")
	{
		Dash * temp = new Dash;
		temp->SetAugName(name);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Double Jump")
	{
		DoubleJump * temp = new DoubleJump;
		temp->SetAugName(name);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Slide")
	{
		Slide * temp = new Slide;
		temp->SetAugName(name);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}
	if (name == "Wall Climb")
	{
		WallClimb * temp = new WallClimb;
		temp->SetAugName(name);
		temp->SetSize({ 20, 20 });
		temp->SetPosition(pos);
		return temp;
	}

	return nullptr;
}

void GameplayState::LoadPlayerFile(string file)
{
	TiXmlDocument xDoc(file.c_str());
	if (xDoc.LoadFile())
	{
		TiXmlElement *xRoot = xDoc.FirstChildElement();
		TiXmlElement *xPlayer = xRoot->FirstChildElement("Player");
		TiXmlElement *xAugments = xRoot->FirstChildElement("Augments");

		int tempNextLevel = 0, tempScore = 0;
		xPlayer->Attribute("level", &tempNextLevel);
		xPlayer->Attribute("score", &tempScore);

		player->SetName(xPlayer->Attribute("name"));
		player->SetNextLevel(tempNextLevel);
		if (tempNextLevel >= 5)
			gameComplete = true;
		player->SetScore(tempScore);

		/*
		TiXmlElement *xAugment = xAugments->FirstChildElement("Augment");
		for (int i = 0; xAugment; xAugment->NextSiblingElement("Augment"))
		{
		string type = xAugment->Attribute("type");
		string slot = xAugment->Attribute("slot");

		Augment *aug = dynamic_cast<Augment *>(CreateAugment({ -1.0f, -1.0f }, type));

		if (slot == "move")
		{
		if (!player->GetMoveSlot()) player->SetMoveSlot(aug);
		else if (!player->GetHotSwap(0)) player->SetHotSwap(0, aug);
		else if (!player->GetHotSwap(1)) player->SetHotSwap(1, aug);
		else if (!player->GetHotSwap(2)) player->SetHotSwap(2, aug);
		else if (!player->GetHotSwap(3)) player->SetHotSwap(3, aug);
		else player->AddMoveTable(aug);
		}
		else if (slot == "bullet")
		{
		if (!player->GetBulletSlot()) player->SetBulletSlot(aug);
		else if (!player->GetHotSwap(0)) player->SetHotSwap(0, aug);
		else if (!player->GetHotSwap(1)) player->SetHotSwap(1, aug);
		else if (!player->GetHotSwap(2)) player->SetHotSwap(2, aug);
		else if (!player->GetHotSwap(3)) player->SetHotSwap(3, aug);
		else player->AddWeaponTable(aug);
		}
		else if (slot == "shot")
		{
		if (!player->GetStyleSlot()) player->SetBulletSlot(aug);
		else if (!player->GetHotSwap(0)) player->SetHotSwap(0, aug);
		else if (!player->GetHotSwap(1)) player->SetHotSwap(1, aug);
		else if (!player->GetHotSwap(2)) player->SetHotSwap(2, aug);
		else if (!player->GetHotSwap(3)) player->SetHotSwap(3, aug);
		else player->AddWeaponTable(aug);
		}

		i++;
		}
		*/
	}
}

void GameplayState::SavePlayerFile(string file)
{
	TiXmlDocument doc;
	TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
	TiXmlElement *xGame = new TiXmlElement("Game");
	TiXmlElement *xPlayer = new TiXmlElement("Player");
	TiXmlElement *xAugments = new TiXmlElement("Augments");
	doc.LinkEndChild(decl);
	doc.LinkEndChild(xGame);
	xGame->LinkEndChild(xPlayer);
	xGame->LinkEndChild(xAugments);

	xPlayer->SetAttribute("name", player->GetName().c_str());
	xPlayer->SetAttribute("level", player->GetNextLevel());
	xPlayer->SetAttribute("score", player->GetScore());
	/*
	if (player->GetMoveSlot())
	{
	TiXmlElement *xAugment = new TiXmlElement("Augment");
	xAugment->SetAttribute("type", player->GetMoveSlot()->GetAugName().c_str());
	xAugment->SetAttribute("slot", "move");
	xAugments->LinkEndChild(xAugment);
	}
	if (player->GetBulletSlot())
	{
	TiXmlElement *xAugment = new TiXmlElement("Augment");
	xAugment->SetAttribute("type", player->GetBulletSlot()->GetAugName().c_str());
	xAugment->SetAttribute("slot", "bullet");
	xAugments->LinkEndChild(xAugment);
	}
	if (player->GetStyleSlot())
	{
	TiXmlElement *xAugment = new TiXmlElement("Augment");
	xAugment->SetAttribute("type", player->GetStyleSlot()->GetAugName().c_str());
	xAugment->SetAttribute("slot", "shot");
	xAugments->LinkEndChild(xAugment);
	}
	for (int i = 0; i < 4; i++)
	{
	if (!player->GetHotSwap(i)) continue;

	TiXmlElement *xAugment = new TiXmlElement("Augment");
	xAugment->SetAttribute("type", player->GetHotSwap(i)->GetAugName().c_str());
	xAugment->SetAttribute("slot", (player->GetHotSwap(i)->GetAugType() == Augment::AUG_WEP) ? "shot" : "move");
	xAugments->LinkEndChild(xAugment);
	}
	for (unsigned int i = 0; player->GetMoveTable(i); i++)
	{
	TiXmlElement *xAugment = new TiXmlElement("Augment");
	xAugment->SetAttribute("type", player->GetMoveTable(i)->GetAugName().c_str());
	xAugment->SetAttribute("slot", "shot");
	xAugments->LinkEndChild(xAugment);
	}
	for (unsigned int i = 0; player->GetWeaponTable(i); i++)
	{
	TiXmlElement *xAugment = new TiXmlElement("Augment");
	xAugment->SetAttribute("type", player->GetWeaponTable(i)->GetAugName().c_str());
	xAugment->SetAttribute("slot", "shot");
	xAugments->LinkEndChild(xAugment);
	}
	*/
	doc.SaveFile(file.c_str());
}

Augment* GameplayState::RandomizeAugment()
{
	int randomnumber = rand() % 5;
	Augment* temp;
	switch (randomnumber)
	{

	case 0:
		temp = (Augment*)CreateAugment({ -100.0f, -100.0f }, "Arcane Shot");
		break;
	case 1:
		temp = (Augment*)CreateAugment({ -100.0f, -100.0f }, "Solar Flare");
		break;
	case 2:
		temp = (Augment*)CreateAugment({ -100.0f, -100.0f }, "Fire Blast");
		break;
	case 3:
		temp = (Augment*)CreateAugment({ -100.0f, -100.0f }, "Seeker Sludge");
		break;
	case 4:
		temp = (Augment*)CreateAugment({ -100.0f, -100.0f }, "Shockwave");
		break;
	};
	return temp;
}

bool GameplayState::CheckCharacterCollision(SGD::Rectangle pastRect, SGD::Rectangle currRect, SGD::Rectangle otherRect)
{
	// distance moved on x
	//if (currRect.right > otherRect.left && currRect.left < otherRect.left) // collision on left
	if (pastRect.right < otherRect.left) // collision on left
		movedX = abs(currRect.right - pastRect.right);
	//else if (currRect.left < otherRect.right && currRect.right > otherRect.right) // collision on right
	else if (pastRect.left > otherRect.right) // collision on right
		movedX = abs(currRect.left - pastRect.left);

	// distance moved on y
	//if (currRect.bottom > otherRect.top && currRect.bottom < otherRect.bottom) // collision on top
	if (pastRect.bottom < currRect.bottom) // collision on top
		movedY = abs(currRect.bottom - pastRect.bottom);
	//if (currRect.top < otherRect.bottom && currRect.bottom > otherRect.bottom) // collision on bottom
	else if (pastRect.top > currRect.top) // collision on bottom
		movedY = abs(currRect.top - pastRect.top);

	// distanceX between past and other
	float distX = 0;
	if (pastRect.right < otherRect.left) // collision on left
		distX = abs(otherRect.left - pastRect.right);
	else if (pastRect.left > otherRect.right) // collision on right
		distX = abs(otherRect.right - pastRect.left);

	// distance moved on y
	float distY = 0;
	if (pastRect.bottom < currRect.bottom) // collision on top
		distY = abs(otherRect.top - pastRect.bottom);
	else if (pastRect.top > currRect.top) // collision on bottom
		distY = abs(pastRect.top - otherRect.bottom);

	// calculate intersection between current and other
	SGD::Rectangle intersection = currRect.ComputeIntersection(otherRect);
	// calculate itersection size
	sizeX = abs(intersection.right - intersection.left);
	sizeY = abs(intersection.bottom - intersection.top);

	// determine side of collision
	left = top = right = bottom = false;
	if (movedX <= sizeX + distX)
	{
		//if (currRect.right > otherRect.left && currRect.left < otherRect.left) // collision on left
		if (pastRect.right < otherRect.left) // collision on left
			left = true;
		//else if (currRect.left < otherRect.right && currRect.right > otherRect.right) // collision on right
		else if (pastRect.left > otherRect.right) // collision on right
			right = true;
	}
	if (movedY <= sizeY + distY)
	{
		//if (currRect.bottom > otherRect.top && currRect.bottom < otherRect.bottom) // collision on top
		if (pastRect.bottom < currRect.bottom) // collision on top
			top = true;
		//if (currRect.top < otherRect.bottom && currRect.bottom > otherRect.bottom) // collision on bottom
		else if (pastRect.top > currRect.top) // collision on bottom
			bottom = true;
	}
	if (left || top || right || bottom)
		return true;
	return false;
}
